﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using iText.IO.Font;
using iText.Kernel.Font;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;

using System.Text.Json;
using System.Collections;
using iText.Layout.Borders;
using iText.Kernel.Colors;
using System;
using iText.Layout.Properties;
using iText.Html2pdf;
using iText.Layout.Font;
using iText.Kernel.Pdf.Canvas;
using iText.Layout.Layout;
using iText.Kernel.Pdf.Xobject;
using System.Text.RegularExpressions;
using iText.Html2pdf.Resolver.Font;
using iText.Layout.Renderer;
using System.Collections.Concurrent;


namespace cellreport
{
    public class Program
    {
        public static void Main(string[] args)
        {
        }
    }
    public class Html2Pdf
    {        /// <summary>
             /// 常用中文字体中文名称到家族名称（Font Family Name）的对照表
             /// 键（Key）：字体中文名称
             /// 值（Value）：字体元数据中的家族名称（iText匹配font-family的依据）
             /// </summary>
        public static readonly Dictionary<string, string> _chineseToFontFamilyMap = new Dictionary<string, string>
        {
            { "宋体", "SimSun" },
            { "新宋体", "NSimSun" },
            { "黑体", "SimHei" },
            { "微软雅黑", "Microsoft YaHei" },
            { "微软雅黑UI", "Microsoft YaHei UI" },
            { "楷体", "KaiTi" },
            { "楷体_GB2312", "KaiTi_GB2312" },
            { "华文隶书", "STLiti" },
            { "华文魏碑", "STWeiBei" },
            { "仿宋", "FangSong" },
            { "仿宋_GB2312", "FangSong_GB2312" },
            { "幼圆", "YouYuan" },
            { "华文中宋", "STZhongsong" },
            { "华文仿宋", "STFangsong" },
            { "华文行楷", "STXingkai" },
            { "华文楷体", "STKaiti" },
            { "方正舒体", "FZShuTi" },
            { "方正姚体", "FZYaoTi" }
        };
        /// <summary>
        /// 处理font-family的值（可能包含多个字体名称）
        /// </summary>
        private static string ProcessFontFamilyValue(string fontValue)
        {
            string[] fontNames = fontValue.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 0; i < fontNames.Length; i++)
            {
                string fontName = fontNames[i].Trim().Trim('\'').Trim('"');

                if (IsChineseFontName(fontName) &&
                    _chineseToFontFamilyMap.TryGetValue(fontName, out string familyName))
                {
                    fontNames[i] = familyName;
                }
            }

            return string.Join(", ", fontNames);
        }
        // 改进的正则表达式，支持三种结尾情况：
        // 1. 以分号结尾（font-family:宋体;）
        // 2. 以引号结尾（font-family:宋体' 或 font-family:宋体"）
        // 3. 以空格分隔其他属性（font-family:宋体 ...）
        Regex font_regex = new Regex(
            @"(font-family\s*:\s*)(['""]?)(.*?)\2\s*(?=[;'""]|\s|>)",
            RegexOptions.IgnoreCase
        );
        /// <summary>
        /// 判断是否为中文字体名称（包含中文字符）
        /// </summary>
        private static bool IsChineseFontName(string fontName)
        {
            // 匹配任何中文字符（包括简体、繁体等）
            return Regex.IsMatch(fontName, @"[\u4e00-\u9fa5]");
        }
        private dynamic configuration;
        private ConcurrentDictionary<string, PdfFont> font_cache = new ConcurrentDictionary<string, PdfFont>();
        private static bool has_init = false;
        private static Object lock_obj = new();
        static FontProvider fontProvider= new DefaultFontProvider(true, true, false);
        public Html2Pdf(Object configuration, int LocalPort)
        {
            this.configuration = configuration;
            if (!has_init)
            {
                lock (lock_obj)
                {
                    if (!has_init)
                    {
                        PdfFontFactory.RegisterSystemDirectories();
                        //fontProvider = new DefaultFontProvider(true, true, false);
                        // 如果发现字体显示不对，就需要调整字体顺序。
                        for (int idx = 0 ; idx < 1000; idx++)
                        {
                            var cur_font = this.configuration["pdf_fonts" + ":" + idx];
                            if (cur_font == null)
                                break;
                            FontProgram fontProgram = FontProgramFactory.CreateFont(cur_font);
                            fontProvider.AddFont(fontProgram);
                        }
                        fontProvider.AddSystemFonts();
                        has_init = true;
                    }
                }
            }
            converterProperties = new ConverterProperties();
            converterProperties.SetFontProvider(fontProvider);
            converterProperties.SetCharset("utf-8");
            converterProperties.SetBaseUri($"http://127.0.0.1:{LocalPort}/");
        }
        public Func<Object, JsonElement, bool, bool> output_impl;
        public byte[] buildPdf(JsonElement json_root, dynamic ps)
        {
            var json_data = json_root.GetProperty("data");
            //https://api.itextpdf.com/iText7/dotnet/latest/classi_text_1_1_layout_1_1_element_1_1_area_break.html
            var grid_list = json_data.EnumerateObject().Select(x => x.Name).ToList();

            if (ps.pageSize_name != "自定义")
            {
                PageSize _PageSize = typeof(PageSize).GetField(ps.pageSize_name.ToUpper()).GetValue(null) as PageSize;
                if (ps.orientation == "landscape")
                    _PageSize = _PageSize.Rotate();
                ps.pageSize_Width = _PageSize.GetWidth();
                ps.pageSize_Height = _PageSize.GetHeight();
            }

            MemoryStream stream = new();
            PdfWriter writer = new(stream);
            pdfDocument = new(writer);
            try
            {
                //default_font = CellReport.running.Template.getTemplate("template.xml").Get("FONT").content;
                default_font = json_root.GetProperty("defaultsetting").GetProperty("FONT").GetString();
                
                if (converterProperties == null)
                {
                    
                }
                Document pdf_doc = new(pdfDocument, new PageSize(ps.pageSize_Width, ps.pageSize_Height)
                    , false);
                pdf_doc.SetMargins(ps.margin_top, ps.margin_right, ps.margin_bottom, ps.margin_left);
                sysFont = PdfFontFactory.CreateRegisteredFont(default_font, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED, true);
                pdf_doc.SetFont(sysFont).SetFontSize(11);//设置字体大小
                bool is_first = true;
                foreach (var item in json_data.EnumerateObject())
                {
                    //dynamic rg = ReportGridJSON.GetConstructors()[0].Invoke(new object[] { item.Value, ps, addTable });
                    //rg.output(pdf_doc, ref is_first);
                    is_first = this.output_impl(pdf_doc, item.Value, is_first);
                }
                add_header_footer(ps, pdfDocument, pdf_doc, json_root.GetProperty("_zb_var_"));

                //
                pdf_doc.Flush();
            }
            finally
            {
                pdfDocument.Close();//记得关闭PdfDocument和PdfWriter
                writer.Close();
            }
            return stream.ToArray();
        }
        PdfDocument pdfDocument;
        PdfFont sysFont;
        private ConverterProperties converterProperties = null;

        public string default_font { get; private set; }

        private Paragraph convert_html_to_paragraph(string html)
        {
            var retpp = new Paragraph();
            var t_list = HtmlConverter.ConvertToElements(html, converterProperties);
            foreach (var one_ele in t_list)
            {
                retpp.Add(one_ele as IBlockElement);
            }
            return retpp;
        }
        private static Regex r = new(@"&\[(.*?)\]"); //[^\\]#.*#
        private Paragraph replace_var_to_Paragraph(string str, Dictionary<String, object> mark_dict = null)
        {//&[页码]&[总页数]&[日期]&[时间]
            MatchCollection mc = r.Matches(str);//替换#xxx#为 ?,同时记录位置
            foreach (Match a in mc)
            {
                str = str.Replace(a.Value, mark_dict.GetValueOrDefault(a.Groups[1].Value)?.ToString());
            }

            return convert_html_to_paragraph(str);
        }
        private void add_header_footer(dynamic ps, PdfDocument pdf, Document pdf_doc, JsonElement zb_var)
        {
            zb_var.TryGetProperty("watermark", out var watermark);


            var pp = new Paragraph();
            int n = pdf.GetNumberOfPages();
            Dictionary<String, object> mark_dict = new Dictionary<string, object>()
            {
                {"日期", DateTime.Now.ToString("yyyy-MM-dd")},
                {"时间", DateTime.Now.ToString("hh:ss:mm")},
                {"watermark_txt", ""},
                {"watermark_x", 20}, //水印起始位置x轴坐标
                {"watermark_y", 20}, //水印起始位置Y轴坐标
                {"watermark_rows", 20}, //水印行数
                {"watermark_cols", 20}, //水印列数
                {"watermark_x_space", 100}, //水印x轴间隔
                {"watermark_y_space", 50}, //水印y轴间隔
                {"watermark_color", "#aaa"}, //水印字体颜色
                {"watermark_alpha", 0.4}, //水印透明度
                {"watermark_fontsize", "15px"}, //水印字体大小
                {"watermark_font", "微软雅黑"}, //水印字体
                {"watermark_width", 110}, //水印宽度
                {"watermark_height", 40}, //水印长度
                {"watermark_angle", 20 }//水印倾斜度数
            };
            foreach (var item in zb_var.EnumerateObject())
            {
                mark_dict[item.Name] = item.Value.ToString();
            }
            if (watermark.ValueKind == JsonValueKind.Object)
            {
                foreach (var one in watermark.EnumerateObject())
                {
                    if (one.Value.ValueKind == JsonValueKind.String)
                        mark_dict[one.Name] = one.Value.GetString();
                    if (one.Value.ValueKind == JsonValueKind.Number)
                        mark_dict[one.Name] = one.Value.GetDouble();
                }
            }
            else if (watermark.ValueKind == JsonValueKind.Undefined)
            {

            }
            else
                mark_dict["watermark_txt"] = watermark.GetString();
            var watermark_txt = mark_dict["watermark_txt"].ToString();
            var watermark_x = float.Parse(mark_dict["watermark_x"].ToString());//水印起始位置x轴坐标
            var watermark_y = float.Parse(mark_dict["watermark_y"].ToString()); //水印起始位置Y轴坐标
            var watermark_rows = float.Parse(mark_dict["watermark_rows"].ToString()); //水印行数
            var watermark_cols = float.Parse(mark_dict["watermark_cols"].ToString());//水印列数
            var watermark_x_space = float.Parse(mark_dict["watermark_x_space"].ToString()); //水印x轴间隔
            var watermark_y_space = float.Parse(mark_dict["watermark_y_space"].ToString()); //水印y轴间隔
            var watermark_color = new DeviceRgb(System.Drawing.ColorTranslator.FromHtml(mark_dict["watermark_color"].ToString())); //水印字体颜色
            var watermark_alpha = float.Parse(mark_dict["watermark_alpha"].ToString()); //水印透明度
            var _font_size = mark_dict["watermark_fontsize"].ToString();

            var watermark_fontsize = float.Parse(_font_size[0..^2]) * (_font_size[^2..].ToLower() == "px" ? 0.75f : 1); //水印字体大小
            var watermark_font = mark_dict["watermark_font"].ToString(); //水印字体
            var watermark_width = float.Parse(mark_dict["watermark_width"].ToString()); //水印宽度
            var watermark_height = float.Parse(mark_dict["watermark_height"].ToString());//水印长度
            var watermark_angle = 3.14f / 180 * float.Parse(mark_dict["watermark_angle"].ToString());//水印倾斜度数

            var water_mark = new Paragraph(watermark_txt)
                .SetFontColor(watermark_color)//.SetFontFamily(watermark_font)
                .SetFontSize(watermark_fontsize).SetOpacity(watermark_alpha);

            mark_dict["总页数"] = n;
            for (int page_idx = 1; page_idx <= n; page_idx++)
            {
                mark_dict["页码"] = page_idx;
                for (float x = watermark_x; x < ps.pageSize_Width; x += watermark_x_space)
                {
                    for (float y = watermark_y; y < ps.pageSize_Height; y += watermark_y_space)
                    {
                        pdf_doc.ShowTextAligned(water_mark, x, y, page_idx, TextAlignment.CENTER, VerticalAlignment.MIDDLE, watermark_angle);
                    }
                }

                if (!String.IsNullOrEmpty(ps.footer_left))
                {
                    pp = replace_var_to_Paragraph(ps.footer_left, mark_dict);
                    pdf_doc.ShowTextAligned(pp, ps.margin_footer, ps.margin_footer, page_idx, TextAlignment.LEFT,
                   VerticalAlignment.BOTTOM, 0);//footer left BOTTOM
                }

                if (!String.IsNullOrEmpty(ps.footer_right))
                {
                    pp = replace_var_to_Paragraph(ps.footer_right, mark_dict);
                    pdf_doc.ShowTextAligned(pp,
                    ps.pageSize_Width - ps.margin_footer, ps.margin_footer, page_idx, TextAlignment.RIGHT,
                    VerticalAlignment.BOTTOM, 0);//footer RIGHT BOTTOM
                }
                if (!String.IsNullOrEmpty(ps.header_left))
                {
                    pp = replace_var_to_Paragraph(ps.header_left, mark_dict);
                    pdf_doc.ShowTextAligned(pp,
                  ps.margin_footer, ps.pageSize_Height - ps.margin_footer, page_idx, TextAlignment.LEFT,
                  VerticalAlignment.TOP, 0);//header left top
                }
                if (!String.IsNullOrEmpty(ps.header_right))
                {
                    pp = replace_var_to_Paragraph(ps.header_right, mark_dict);
                    pdf_doc.ShowTextAligned(pp,
                  ps.pageSize_Width - ps.margin_footer, ps.pageSize_Height - ps.margin_footer, page_idx, TextAlignment.RIGHT,
                  VerticalAlignment.TOP, 0);//header right TOP
                }
                if (!String.IsNullOrEmpty(ps.header_center))
                {
                    pp = replace_var_to_Paragraph(ps.header_center, mark_dict);
                    pdf_doc.ShowTextAligned(pp,
                   ps.pageSize_Width / 2, ps.pageSize_Height - ps.margin_footer, page_idx, TextAlignment.CENTER,
                   VerticalAlignment.TOP, 0); //header CENTER
                }
                if (!String.IsNullOrEmpty(ps.footer_center))
                {
                    pp = replace_var_to_Paragraph(ps.footer_center, mark_dict);
                    pdf_doc.ShowTextAligned(pp,
                   ps.pageSize_Width / 2, ps.margin_footer, page_idx, TextAlignment.CENTER,
                   VerticalAlignment.BOTTOM, 0);//footer CENTER
                }
            }
        }

        public Table addTable(dynamic rg, List<int> row_list, List<int> col_list)
        {
            List<BitArray> tableBitFlag = new();
            for (int i = 0; i < rg.tableData.Length; i++)
            {
                tableBitFlag.Add(new BitArray(rg.columnlenArr.Count));
            }
            var cols = new List<float>();
            foreach (var one in col_list)
            {
                cols.Add(rg.cols[one]);
            }
            float tbl_height = 0;
            foreach (var one in row_list)
            {
                tbl_height += rg.GetRowHeight(one);
            }
            var pdf_table = new Table(cols.ToArray())// 设置表格列数
                .SetTextAlignment(iText.Layout.Properties.TextAlignment.CENTER)
                .SetPadding(0).SetMargin(0)//.SetMaxWidth(cols.Sum()).SetMaxHeight(tbl_height)
                ;
            pdf_table.StartNewRow();
            foreach (var colNo in col_list)
            {
                var pdf_cell = new iText.Layout.Element.Cell()
                            .SetMinWidth(rg.columnlenArr[colNo]).SetMaxWidth(rg.columnlenArr[colNo])
                            .SetMinHeight(0).SetMaxHeight(0).SetBorder(Border.NO_BORDER)
                            .SetPadding(0);// 不设置为0 ，将导致高度和设置的不同 缺省padding =2


                pdf_table.AddCell(pdf_cell);
            }
            foreach (var rowNo in row_list)
            {
                var row = rg.tableData[rowNo];
                pdf_table.StartNewRow();
                iText.Layout.Element.Cell pdf_cell;
                //pdf_cell = new Cell()
                //            .SetWidth(0).SetMaxWidth(0)
                //            .SetHeight(rg.GetRowHeight(rowNo)).SetBorder(Border.NO_BORDER)
                //            .SetPadding(0);// 不设置为0 ，将导致高度和设置的不同 缺省padding =2
                //pdf_table.AddCell(pdf_cell);

                foreach (var colNo in col_list)
                {
                    if (colNo >= row.Length)
                        continue;
                    var cell_value = row[colNo];
                    if (colNo >= rg.columnlenArr.Count)
                    {
                        break;
                    }
                    if (tableBitFlag[rowNo].Get(colNo))
                    {
                        continue;
                    }
                    tableBitFlag[rowNo].Set(colNo, true);
                    var max_height = rg.GetRowHeight(rowNo);

                    var max_width = rg.columnlenArr[colNo];
                    var r_c = rg.find_config_merge(rowNo, colNo);
                    int rowSpan = 1, colSpan = 1;

                    bool is_lastcol_split_cell = false;
                    bool is_lastrow_split_cell = false;
                    if (r_c == null)
                    {
                        pdf_cell = new iText.Layout.Element.Cell();
                    }
                    else
                    {
                        if (r_c.rs > 1) rowSpan = r_c.rs;
                        if (r_c.cs > 1) colSpan = r_c.cs;
                        if (colNo + colSpan - 1 > col_list.Last())
                        {
                            colSpan = col_list.Last() - colNo + 1;
                            is_lastcol_split_cell = true;
                            rg.insert_merge(rowNo, colNo + colSpan, rowSpan, r_c.cs - colSpan);
                        }
                        if (rowNo + rowSpan - 1 > row_list.Last())
                        {
                            rowSpan = row_list.Last() - rowNo + 1;
                            is_lastrow_split_cell = true;
                            rg.insert_merge(rowNo + rowSpan, colNo, r_c.rs - rowSpan, colSpan);
                        }
                        pdf_cell = new iText.Layout.Element.Cell(rowSpan, colSpan);
                        max_width = 0;// -(colSpan-1)*10f* rg.border_width;
                        for (var ci = 0; ci < colSpan; ci++)
                        {
                            max_width += rg.columnlenArr[colNo + ci];
                        }
                        max_height = 0;// -(rowSpan - 1) * 10f * rg.border_width;
                        for (var ri = 0; ri < rowSpan; ri++)
                        {
                            max_height += rg.GetRowHeight(rowNo + ri);
                            for (var ci = 0; ci < colSpan; ci++)
                            {//这里要用rowNo，因为清单报表的r_c.r 是原始单元格的。r_c.c也应该改为 colNO 
                                tableBitFlag[rowNo + ri]?.Set(colNo + ci, true);
                            }
                        }
                    }
                    pdf_cell.SetBorder(Border.NO_BORDER);
                    float cur_font_size = 0;
                    string cur_font_family = default_font;
                    foreach (var one_style in rg.find_style(rowNo, colNo))
                    {
                        switch (one_style.Key)
                        {
                            case "background-color":
                                pdf_cell.SetBackgroundColor(new DeviceRgb(System.Drawing.ColorTranslator.FromHtml(one_style.Value)));
                                break;
                            case "color":
                                pdf_cell.SetFontColor(new DeviceRgb(System.Drawing.ColorTranslator.FromHtml(one_style.Value)));
                                break;
                            case "font-family":
                                cur_font_family = one_style.Value;
                                if (!font_cache.TryGetValue(one_style.Value, out PdfFont font))
                                {
                                    font = PdfFontFactory.CreateRegisteredFont(one_style.Value, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED, true);
                                    font_cache.TryAdd(one_style.Value, font);
                                }
                                pdf_cell.SetFont(font);
                                //pdf_cell.SetFontFamily(one_style.Value);
                                break;
                            case "FONT-SIZE":
                                cur_font_size = float.Parse(one_style.Value);
                                pdf_cell.SetFontSize(cur_font_size);
                                break;
                            case "font-weight":
                                pdf_cell.SetBold();
                                break;
                            case "BORDER-LEFT":
                                var border_style = (one_style.Value as String).Split();
                                pdf_cell.SetBorderLeft(new SolidBorder(
                                     new DeviceRgb(System.Drawing.ColorTranslator.FromHtml(border_style[1]))
                                    , float.Parse(border_style[0])));
                                break;
                            case "BORDER-RIGHT":
                                if (!is_lastcol_split_cell)
                                {
                                    border_style = (one_style.Value as String).Split();
                                    pdf_cell.SetBorderRight(new SolidBorder(
                                         new DeviceRgb(System.Drawing.ColorTranslator.FromHtml(border_style[1]))
                                        , float.Parse(border_style[0])));
                                }
                                break;
                            case "BORDER-TOP":
                                border_style = (one_style.Value as String).Split();
                                pdf_cell.SetBorderTop(new SolidBorder(
                                     new DeviceRgb(System.Drawing.ColorTranslator.FromHtml(border_style[1]))
                                    , float.Parse(border_style[0])));
                                break;
                            case "BORDER-BOTTOM":
                                if (!is_lastrow_split_cell)
                                {
                                    border_style = (one_style.Value as String).Split();
                                    pdf_cell.SetBorderBottom(new SolidBorder(
                                         new DeviceRgb(System.Drawing.ColorTranslator.FromHtml(border_style[1]))
                                        , float.Parse(border_style[0])));
                                }
                                break;
                            case "vertical-align":
                                switch (one_style.Value.ToString().ToUpper())
                                {
                                    case "TOP":
                                        pdf_cell.SetVerticalAlignment(VerticalAlignment.TOP);
                                        break;
                                    case "BOTTOM":
                                        pdf_cell.SetVerticalAlignment(VerticalAlignment.BOTTOM);
                                        break;
                                    default:
                                        pdf_cell.SetVerticalAlignment(VerticalAlignment.MIDDLE);
                                        break;
                                }

                                break;
                            case "text-align":
                                switch (one_style.Value.ToString().ToUpper())
                                {
                                    case "LEFT":
                                        pdf_cell.SetTextAlignment(TextAlignment.LEFT);
                                        break;
                                    case "RIGHT":
                                        pdf_cell.SetTextAlignment(TextAlignment.RIGHT);
                                        break;
                                    default:
                                        pdf_cell.SetTextAlignment(TextAlignment.CENTER);
                                        break;
                                }

                                break;
                        }
                    }
                    int deta = 0;
                    IBlockElement cur_pp = null;
                    var cur_str = cell_value == null ? "" : cell_value.ToString();
                    cur_str = (String.IsNullOrWhiteSpace(cur_str) ? "<span>&nbsp;</span>" : cur_str);
                    //System.Web.HttpUtility.HtmlDecode(cur_str);
                    if (rg.auto_line_height || cur_str.StartsWith("<"))
                    {
                        if (!font_cache.TryGetValue(cur_font_family, out PdfFont font))
                        {
                            font = PdfFontFactory.CreateRegisteredFont(cur_font_family, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED, true);
                            font_cache.TryAdd(cur_font_family, font);
                        }
                        var t_str = cur_str.Replace("width:100%", $"width:{max_width}pt").Replace("height:100%", $"height:{max_height}pt");
                        var wrap = rg.auto_line_height?"white-space: wrap;word-wrap: break-word;":"";
                        var html = $"<div style='{wrap}font-size:{cur_font_size}pt;width:{max_width}pt;max-height:{0}pt;line-height:normal;font-family:{cur_font_family}'>{t_str}</div>";

                        // 替换匹配到的内容
                        var ttt = font_regex.Replace(html, match =>
                        {
                            // 匹配组说明：
                            // Group 1: "font-family: " 部分
                            // Group 2: 字体名称的引号（可能为空）
                            // Group 3: 字体名称内容
                            string fontContent = match.Groups[3].Value;
                            string processedContent = ProcessFontFamilyValue(fontContent);

                            // 仅替换字体内容，保留原始的引号和结尾格式
                            return $"{match.Groups[1].Value}{match.Groups[2].Value}{processedContent}{match.Groups[2].Value}";
                        });


                        var t_list = HtmlConverter.ConvertToElements(ttt, converterProperties);

                        if (t_list.Count == 1 && t_list[0] is IBlockElement)
                        {
                            iText.Layout.Font.FontProvider fontProvider = new FontProvider(cur_font_family);
                            //(t_list[0] as iText.Layout.Element.Div).SetProperty(91,curFont);
                            cur_pp = (t_list[0] as iText.Layout.Element.Div).SetFont(font).SetFontSize(cur_font_size);

                        }
                        else
                            cur_pp = new Paragraph(cur_str);
                        //HtmlCellHeightCalculator calculator = new HtmlCellHeightCalculator();
                        //float divHeight = calculator.CalculateHtmlDivHeight(t_str2, max_width);
                        //HtmlInTableCellHeightCalculator calculator2 = new();
                        //float divHeight2 = calculator2.CalculateHtmlInCellHeight(t_str2, max_width);
                        //pdf_cell.SetHeight((float)(divHeight * 0.5));

                    }
                    else
                    {
                        if (rowNo == 0 && colNo == 0)
                        {
                            //max_width = 0;
                            //    var new_font_size=shrinkFontSize(cur_str, max_width, max_height);
                            //    pdf_cell.SetFontSize(new_font_size);
                        }
                        cur_pp = new Paragraph(cur_str);
                    }
                    pdf_cell.Add(cur_pp)
                            //replace_var_to_Paragraph(cell_value.ToString(),0,0)
                            .SetMinWidth(max_width - deta).SetMaxWidth(max_width - deta);
                    //if (rg.auto_line_height == false)
                    pdf_cell.SetMinHeight(max_height - deta).SetMaxHeight(max_height - deta);
                    pdf_cell.SetPadding(0)// 不设置为0 ，将导致高度和设置的不同 缺省padding =2
                                          .SetMargin(0)

                            ;

                    pdf_table.AddCell(pdf_cell);
                }
            }

            return pdf_table;
        }
        private float shrinkFontSize(string content, float width, float height)
        {
            Text lineTxt = new Text(content);

            iText.Kernel.Geom.Rectangle lineTxtRect = new iText.Kernel.Geom.Rectangle(1, 1, width, height);

            Div lineDiv = new Div();
            lineDiv.SetVerticalAlignment(VerticalAlignment.MIDDLE);
            lineDiv.SetBorder(Border.NO_BORDER);

            Paragraph linePara = new Paragraph().Add(lineTxt)
                .SetTextAlignment(iText.Layout.Properties.TextAlignment.CENTER)
                .SetBorder(new DottedBorder(1)).SetFont(sysFont)
                .SetMultipliedLeading(0.0f) //行间距
                .SetFixedLeading(0.0f)
                ;
            lineDiv.Add(linePara);

            float fontSizeL = 1; // 1 is the font size that is definitely small enough to draw all the text 
            float fontSizeR = 20; // 20 is the maximum value of the font size you want to use
            PdfFormXObject aaa = new PdfFormXObject(lineTxtRect);
            Canvas canvas = new Canvas(new PdfFormXObject(lineTxtRect), pdfDocument);
            //Canvas canvas = new Canvas(new PdfCanvas(pdfDocument.AddNewPage()), lineTxtRect);

            // Binary search on the font size
            while (Math.Abs(fontSizeL - fontSizeR) > 1e-1)
            {
                float curFontSize = (fontSizeL + fontSizeR) / 2;
                lineDiv.SetFontSize(curFontSize);
                // It is important to set parent for the current element renderer to a root renderer
                var renderer = lineDiv.CreateRendererSubTree().SetParent(canvas.GetRenderer());
                var context = new LayoutContext(new LayoutArea(1, lineTxtRect));
                if (renderer.Layout(context).GetStatus() == LayoutResult.FULL)
                {
                    // we can fit all the text with curFontSize
                    fontSizeL = curFontSize;
                }
                else
                {
                    fontSizeR = curFontSize;
                }
            }
            return fontSizeL;
        }
    }

    public class HtmlCellHeightCalculator
    {
        private ConverterProperties converterProperties;
        public HtmlCellHeightCalculator()
        {
            this.converterProperties = new();
        }
        // 主方法：计算HTML内容在指定宽度下的高度
        public float CalculateHtmlDivHeight(string htmlContent, float cellWidth)
        {
            // 提取HTML中的边距信息
            var margins = ExtractMargins(htmlContent);

            // 创建临时文档用于布局计算
            using (var ms = new MemoryStream())
            using (var writer = new PdfWriter(ms))
            using (var pdfDoc = new PdfDocument(writer))
            {
                // 设置页面宽度与单元格宽度一致
                var doc = new Document(pdfDoc, new PageSize(cellWidth, PageSize.A4.GetHeight()));

                // 转换HTML为iText元素
                var elements = HtmlConverter.ConvertToElements(htmlContent, converterProperties);

                if (elements.Count == 0) return 0;

                // 获取第一个元素（通常是Div）
                var div = elements[0] as Div;
                if (div == null) return 0;

                // 应用边距
                ApplyMargins(div, margins);

                // 设置宽度约束
                div.SetWidth(cellWidth - margins.TotalHorizontal);

                // 使用布局监听捕获高度
                var renderer = new HeightCapturingRenderer(div);
                div.SetNextRenderer(renderer);

                // 执行布局
                doc.Add(div);
                doc.Flush();

                // 返回计算的高度（包含边距）
                return renderer.CalculatedHeight + margins.TotalVertical;
            }
        }

        // 提取HTML中的边距信息
        private HtmlMargins ExtractMargins(string htmlContent)
        {
            var margins = new HtmlMargins();

            // 简单的正则表达式提取margin和padding（实际应用中可能需要更复杂的解析）
            var marginRegex = new Regex(@"margin\s*:\s*(\d+)(\w+)\s*(\d+)(\w+)\s*(\d+)(\w+)\s*(\d+)(\w+)", RegexOptions.IgnoreCase);
            var paddingRegex = new Regex(@"padding\s*:\s*(\d+)(\w+)\s*(\d+)(\w+)\s*(\d+)(\w+)\s*(\d+)(\w+)", RegexOptions.IgnoreCase);

            var marginMatch = marginRegex.Match(htmlContent);
            var paddingMatch = paddingRegex.Match(htmlContent);

            // 解析边距值（示例：假设单位为px）
            if (marginMatch.Success)
            {
                margins.Top = ParseSize(marginMatch.Groups[1].Value, marginMatch.Groups[2].Value);
                margins.Right = ParseSize(marginMatch.Groups[3].Value, marginMatch.Groups[4].Value);
                margins.Bottom = ParseSize(marginMatch.Groups[5].Value, marginMatch.Groups[6].Value);
                margins.Left = ParseSize(marginMatch.Groups[7].Value, marginMatch.Groups[8].Value);
            }

            if (paddingMatch.Success)
            {
                margins.PaddingTop = ParseSize(paddingMatch.Groups[1].Value, paddingMatch.Groups[2].Value);
                margins.PaddingRight = ParseSize(paddingMatch.Groups[3].Value, paddingMatch.Groups[4].Value);
                margins.PaddingBottom = ParseSize(paddingMatch.Groups[5].Value, paddingMatch.Groups[6].Value);
                margins.PaddingLeft = ParseSize(paddingMatch.Groups[7].Value, paddingMatch.Groups[8].Value);
            }

            return margins;
        }

        // 解析尺寸单位（简化版，仅处理px和pt）
        private float ParseSize(string value, string unit)
        {
            if (!float.TryParse(value, out var size)) return 0;

            // 转换常见单位为pt（iText的默认单位）
            switch (unit.ToLower())
            {
                case "px": return size * 0.75f; // 1px ≈ 0.75pt
                case "pt": return size;
                default: return size; // 简化处理，实际应用中需要更全面的单位转换
            }
        }

        // 应用边距到iText元素
        private void ApplyMargins(Div div, HtmlMargins margins)
        {
            div.SetMarginTop(margins.Top);
            div.SetMarginRight(margins.Right);
            div.SetMarginBottom(margins.Bottom);
            div.SetMarginLeft(margins.Left);

            div.SetPaddingTop(margins.PaddingTop);
            div.SetPaddingRight(margins.PaddingRight);
            div.SetPaddingBottom(margins.PaddingBottom);
            div.SetPaddingLeft(margins.PaddingLeft);
        }
    }

    // 高度捕获渲染器
    public class HeightCapturingRenderer : DivRenderer
    {
        public float CalculatedHeight { get; private set; }

        public HeightCapturingRenderer(Div modelElement) : base(modelElement) { }

        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            var result = base.Layout(layoutContext);

            if (result.GetStatus() == LayoutResult.FULL ||
                result.GetStatus() == LayoutResult.PARTIAL)
            {
                // 计算内容高度
                var area = layoutContext.GetArea().GetBBox();
                var occupiedArea = result.GetOccupiedArea().GetBBox();
                CalculatedHeight = area.GetHeight() - occupiedArea.GetY() + occupiedArea.GetHeight();
            }

            return result;
        }
    }

    // 边距信息类
    public class HtmlMargins
    {
        public float Top { get; set; }
        public float Right { get; set; }
        public float Bottom { get; set; }
        public float Left { get; set; }

        public float PaddingTop { get; set; }
        public float PaddingRight { get; set; }
        public float PaddingBottom { get; set; }
        public float PaddingLeft { get; set; }

        public float TotalHorizontal => Left + Right + PaddingLeft + PaddingRight;
        public float TotalVertical => Top + Bottom + PaddingTop + PaddingBottom;
    }
    public class HtmlInTableCellHeightCalculator
    {
        public float CalculateHtmlInCellHeight(string htmlContent, float cellWidth, float maxHeight = float.MaxValue)
        {
            using (var ms = new MemoryStream())
            using (var writer = new PdfWriter(ms))
            using (var pdfDoc = new PdfDocument(writer))
            {
                // 创建足够大的页面以容纳内容
                var pageSize = new PageSize(cellWidth + 50, maxHeight); // 留出边距
                var doc = new Document(pdfDoc, pageSize);

                // 创建1x1表格
                var table = new Table(UnitValue.CreatePercentArray(1));
                table.SetWidth(cellWidth);

                // 创建单元格并添加HTML内容
                var cell = new Cell();
                cell.SetPadding(0); // 移除单元格内边距，以便精确控制

                // 转换HTML并添加到单元格
                var converterProperties = new ConverterProperties();
                var elements = HtmlConverter.ConvertToElements(htmlContent, converterProperties);

                foreach (var element in elements)
                {
                    cell.Add((IElement)element as iText.Layout.Element.Div);
                }

                // 添加单元格到表格
                table.AddCell(cell);

                // 使用布局监听捕获表格高度
                var renderer = new TableHeightCapturingRenderer(table);
                table.SetNextRenderer(renderer);

                // 添加表格到文档
                doc.Add(table);
                doc.Flush();

                // 返回计算的表格高度
                return renderer.CalculatedHeight;
            }
        }
    }

    // 表格高度捕获渲染器
    public class TableHeightCapturingRenderer : TableRenderer
    {
        public float CalculatedHeight { get; private set; }

        public TableHeightCapturingRenderer(Table modelElement) : base(modelElement) { }

        public override LayoutResult Layout(LayoutContext layoutContext)
        {
            var result = base.Layout(layoutContext);

            if (result.GetStatus() == LayoutResult.FULL ||
                result.GetStatus() == LayoutResult.PARTIAL)
            {
                // 获取表格占用的区域
                var occupiedArea = result.GetOccupiedArea();
                var bbox = occupiedArea.GetBBox();

                // 计算表格高度（包括边框）
                CalculatedHeight = bbox.GetHeight();
            }

            return result;
        }
    }
}

